package com.example.demo.common.zookeeper;

import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.CountDownLatch;

/**
 * 官方自带的zookeeper客户端存在的问题
 * session会话超时异常时，不支持自动重连，需要手动重新连接，编程繁琐（生产环境中如果网络出现不稳定情况，那么这种情况出现的更加明显）
 * ZooKeeper的watcher监听是一次性的，注册一次后会失效
 * 节点数据是二进制，对象数据都需要转换为二进制保存
 * 不支持递归创建节点，需要先创建父节点再创建子节点
 * 不支持递归删除节点，需要先删除子节点再删除父节点
 * 没有领导选举机制，集群情况下可能需要实现stand by，一个服务挂了，另一个需要接替的效果
 * 客户端只提供了存储byte数组的接口，而项目中一般都会使用对象
 * 客户端接口需要处理的异常太多，并且通常，我们也不知道如何处理这些异常
 * 原生zookeeper客户端和服务器端会话的建立是一个异步的过程，也就是说在程序中，我们程序方法在处理完客户端初始化后，立即返回(程序往下执行代码，这样，大多数情况下我们并没有真正构建好一个可用会话，在会话的声明周期处于”CONNECTED”时才算真正建立完毕，所以我们需要使用多线程中的一个工具类CountDownLatch来控制，真正的连接上zk客户端后，才可以继续操作zNode节点)
 */
//@Configuration
@Slf4j
public class ZookeeperConfig {
    @Value("${spring.zookeeper.address}")
    private String connectString;

    @Value("${spring.zookeeper.timeout}")
    private int timeout;

    @Bean(name = "zkClient")
    public ZooKeeper zkClient() {
        ZooKeeper zooKeeper = null;
        try {
            final CountDownLatch countDownLatch = new CountDownLatch(1);
            //连接成功后，会回调watcher监听，此连接操作是异步的，执行完new语句后，直接调用后续代码
            //  可指定多台服务地址 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
            zooKeeper = new ZooKeeper(connectString, timeout, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    if (Watcher.Event.KeeperState.SyncConnected == event.getState()) {
                        //如果收到了服务端的响应事件,连接成功
                        countDownLatch.countDown();
                    }
                }
            });
            countDownLatch.await();
            log.info("【初始化ZooKeeper连接状态....】={}", zooKeeper.getState());

        } catch (Exception e) {
            log.error("初始化ZooKeeper连接异常....】={}", e);
        }
        return zooKeeper;
    }
}
